<?php
class CcbNotify
{
    private $host = '127.0.0.1';
    private $port = 55533;
    private $ccb_config;
    private $errorMessage = '';

    public function __construct($ccb_config)
    {
        $this->ccb_config = $ccb_config;
    }

    /**
     * 反馈参数验证
     * @return 验证结果
     */
    public function verifyNotify($para)
    {
        if(empty($para) || !isset($para['SUCCESS']) || $para['SUCCESS'] !== 'Y') {//判断传过来的数组是否为空
            $this->errorMessage = '传过来的参数为空，或成功状态异常';
            return FALSE;
        } else {
            return $this->signVeryfy($para);
        }
    }

    /**
     * 建立签名验证说需要的参数
     * @param  [type] $para [description]
     */
    private function buildSignSrc($para)
    {
        if ( !isset($para['POSID']) || $para['POSID'] != $this->ccb_config['POSID']) {
            $this->errorMessage = '反馈回来的地址参数不符';
            return FALSE;
        }

        if ( !isset($para['BRANCHID']) || $para['BRANCHID'] != $this->ccb_config['BRANCHID']) {
            $this->errorMessage = '反馈回来的地址参数不符';
            return FALSE;
        }

        if ( empty($para['ORDERID']) || $para['ORDERID'] <= 0) {
            $this->errorMessage = '反馈回来的参数不符';
            return FALSE;
        }

        if ( empty($para['PAYMENT']) || $para['PAYMENT'] <= 0) {
            $this->errorMessage = '反馈回来的参数不符';
            return FALSE;
        }

        if ( !isset($para['CURCODE']) || $para['CURCODE'] != $this->ccb_config['CURCODE']) {
            $this->errorMessage = '反馈回来的参数不符';
            return FALSE;
        }

        if ( !isset($para['TYPE']) || $para['TYPE'] != $this->ccb_config['TYPE']) {
            $this->errorMessage = '反馈回来的参数不符';
            return FALSE;
        }

        if ( !isset($para['REFERER']) || $para['REFERER'] != $this->ccb_config['REFERER']) {
            $this->errorMessage = '反馈回来的参数不符';
            return FALSE;
        }

        $src = 'POSID='. $this->ccb_config['POSID'].
                '&BRANCHID='. $this->ccb_config['BRANCHID'].
                '&ORDERID='. $para['ORDERID'].
                '&PAYMENT='. $para['PAYMENT'].
                '&CURCODE='. $this->ccb_config['CURCODE'].
                '&REMARK1='. $para['REMARK1'].
                '&REMARK2='. $para['REMARK2'];
        if (isset($para['ACC_TYPE'])) { //仅服务器通知中有此字段,返回且参与验签
            $src .= '&ACC_TYPE='. $para['ACC_TYPE'];
        }

        $src .= '&SUCCESS=' . $para['SUCCESS'].
                '&TYPE='. $this->ccb_config['TYPE'].
                '&REFERER='. $this->ccb_config['REFERER'].
                '&CLIENTIP='. $para['CLIENTIP'];

        if (isset($para['ACCDATE'])) {
            $src .= '&ACCDATE='. $para['ACCDATE'];
        }

        if (isset($para['USRMSG'])) {
            $src .= '&USRMSG='. $para['USRMSG'];
        }

        $src .= '&SIGN='. $para['SIGN'];
        return $src;
    }

    /**
     * socket通信 验证签名是否正确
     * @return [type] [description]
     */
    private function signVeryfy($tmpParam)
    {
        $sendData = $this->buildSignSrc($tmpParam). "\n";
        if (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE) {
            $this->errorMessage = "SOCKET连接失败原因: ($result) " . socket_strerror($result);
            return FALSE;
        }

        $result = socket_connect($socket, $this->host, $this->port);
        if ($result < 0) {
            $this->errorMessage = "SOCKET连接失败原因: ($result) " . socket_strerror($result);
            return FALSE;
        }

        //发送命令
        socket_write($socket, $sendData, strlen($sendData));
        $buf = socket_read($socket,8192);
        socket_close($socket);

        $buf = explode("|", $buf);
        if ($buf[0] === 'Y') {
            return TRUE;
        }else {
            $this->errorMessage = '验签失败';
            return FALSE;
        }
    }

    /**
     * 获取错误消息
     * @return string
     */
    public function getErrorMessages()
    {
        return $this->errorMessage;
    }
}